﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Binalyse.Memory;

namespace Binalyse
{
    public partial class SelectProcessDialog : Form
    {
        struct ProcessInfo
        {
            public uint ProcessId;
            public string ExeFile;
            public override string ToString()
            {
                return string.Format("[{0:X8}] {1}", ProcessId, ExeFile);
            }
        }
        struct ModuleInfo
        {
            public IntPtr Address;
            public string PathName;
            public string Name;
            public override string ToString()
            {
                return string.Format("[{0:X8}] {1}", Address.ToInt32(), PathName);
            }
        }
        public uint ProcessId
        {
            get;
            set;
        }
        public string ProcessName
        {
            get;
            set;
        }
        public string ModuleName
        {
            get;
            set;
        }
        public IntPtr ModuleAddress
        {
            get;
            set;
        }
        public void RefreshProcessesList()
        {
            IntPtr hSnapshot = Win32API.CreateToolhelp32Snapshot(Win32API.TH32CS_SNAPPROCESS, 0);
            comboBox_processes.Items.Clear();
            listBox_modules.Items.Clear();
            if (hSnapshot != Win32API.INVALID_HANDLE_VALUE)
            {
                PROCESSENTRY32 pe = new PROCESSENTRY32();
                pe.Size = (uint)Marshal.SizeOf(pe);
                for (bool bOk = Win32API.Process32First(hSnapshot, ref pe);
                    bOk;
                    bOk = Win32API.Process32Next(hSnapshot, ref pe))
                {
                    if (pe.ProcessID != 0 && pe.ProcessID != 4)
                    {
                        ProcessInfo pi = new ProcessInfo();
                        pi.ProcessId = pe.ProcessID;
                        pi.ExeFile = pe.ExeFile;
                        comboBox_processes.Items.Add(pi);
                    }
                }
                Win32API.CloseHandle(hSnapshot);
            }
        }
        public void RefreshModulesList(uint processId)
        {
            IntPtr hSnapshot = Win32API.CreateToolhelp32Snapshot(Win32API.TH32CS_SNAPMODULE, processId);
            listBox_modules.Items.Clear();

            if (hSnapshot != Win32API.INVALID_HANDLE_VALUE)
            {
                MODULEENTRY32 me = new MODULEENTRY32();
                me.Size = (uint)Marshal.SizeOf(me);
                for (bool bOk = Win32API.Module32First(hSnapshot, ref me);
                    bOk;
                    bOk = Win32API.Module32Next(hSnapshot, ref me))
                {
                    ModuleInfo mi = new ModuleInfo();
                    mi.PathName = me.ExePath;
                    mi.Address = me.BaseAddr;
                    mi.Name = me.Module;
                    listBox_modules.Items.Add(mi);
                }
                Win32API.CloseHandle(hSnapshot);
            }
#if DEBUG
            else 
            {
                uint errorCode = Win32API.GetLastError();
                MessageBox.Show(string.Format("搜索模块出错，错误代码:{0}", errorCode), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
#endif
        }
        public SelectProcessDialog()
        {
            InitializeComponent();
            RefreshProcessesList();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            if (comboBox_processes.SelectedIndex < 0)
            {
                MessageBox.Show("你必须选择一个进程!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (listBox_modules.SelectedIndex < 0)
            {
                MessageBox.Show("你必须选择一个进程模块!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ProcessInfo info = (ProcessInfo)comboBox_processes.SelectedItem;
            ProcessId = info.ProcessId;
            ProcessName = info.ExeFile;
            ModuleInfo mi = (ModuleInfo)listBox_modules.SelectedItem;
            ModuleName = mi.Name;
            ModuleAddress = mi.Address;
            DialogResult = DialogResult.OK;
            Close();
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }

        private void button_refreshProcesses_Click(object sender, EventArgs e)
        {
            RefreshProcessesList();
           
        }

        private void button_refleshModules_Click(object sender, EventArgs e)
        {
            if (comboBox_processes.SelectedIndex >= 0)
            {
                ProcessInfo info = (ProcessInfo)comboBox_processes.SelectedItem;
                RefreshModulesList(info.ProcessId);
            }
        }

        private void comboBox_processes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox_processes.SelectedIndex >= 0)
            {
                ProcessInfo info = (ProcessInfo)comboBox_processes.SelectedItem;
                RefreshModulesList(info.ProcessId);
            }
        }
    }
}
